﻿using Peninsula.DataAccess.POCO;
using System;
using System.Collections.Generic;
using System.Linq;
using Peninsula.Utility.Extensions;
using Peninsula.Account.common;
using System.Linq.Expressions;
using Peninsula.Common.Exceptions;

namespace Peninsula.Account.Manager
{
    public class HouseholdsManger : ManagerBase
    {
        public IQueryable<Households> Householdses { get { return HouseholdsProvider.Entities; } }
        public virtual bool VaildateHouseholds(string housrholdsName, string password) {

            bool isLockedOut;
            return VaildateHouseholds(housrholdsName, password, out isLockedOut);
        }

        public virtual bool VaildateHouseholds(string housrholdsName, string password, out bool isLockedOut)
        {
            var households = HouseholdsProvider.Get(h => h.UserName == housrholdsName);
            isLockedOut = false;

            Setting setting = this.SettingProvider.Get();

            bool valid = false;
            if (households != null)
            {
                var encodedPassword = PasswordProvider.EncryptPassword(password);
                valid = encodedPassword == households.Password;

                //超时解锁
                if (households.IsLockedOut && households.LastLockoutDate.HasValue
                    && households.LastLockoutDate.Value.AddMinutes(setting.MinutesToUnlock) < DateTime.Now)
                {
                    households.FailedPasswordAttemptCount = 0;
                    households.IsLockedOut = false;
                }

                //验证成功
                if (valid)
                {
                    households.FailedPasswordAttemptCount = 0;
                    households.IsLockedOut = isLockedOut = false;
                    households.LastLoginDate = DateTime.Now;
                }
                else//锁定账户
                {
                    households.FailedPasswordAttemptCount++;
                    if (households.FailedPasswordAttemptCount >= setting.FailedPasswordAttemptCount)
                    {
                        households.IsLockedOut = isLockedOut = true;
                        households.LastLockoutDate = DateTime.Now;
                    }
                }

                Update(households);
            }
            return valid;
        }
        public virtual Households Get(string householdsName) {
            return HouseholdsProvider.Get(h => h.UserName == householdsName);
        }

        public virtual Households Get(Expression<Func<Households, bool>> predicate) {
            return HouseholdsProvider.Get(predicate);
        }

        public virtual void Update(Households households)
        {
            Vaildate(households, false);
            HouseholdsProvider.Update(households);

        }


        /// <summary>
        /// 添加
        /// </summary>
        /// <param name="households"></param>
        /// <returns></returns>
        public virtual bool Add(Households households) {
            Vaildate(households);
            households.Password = PasswordProvider.EncryptPassword(households.Password);
            return HouseholdsProvider.Insert(households) > 0;
        }

        public virtual bool Delete(string householdsNams, bool isSave = true)
        {
            return HouseholdsProvider.Delete(a => a.UserName == householdsNams, isSave: isSave) > 0;
        }

        public virtual bool Delete(Expression<Func<Households, bool>> predicate)
        {
            return HouseholdsProvider.Delete(predicate) > 0;
        }
        public virtual IEnumerable<Households> All()
        {
            return HouseholdsProvider.Entities.AsEnumerable();
        }
        public virtual IQueryable<Households> GetAll() {
            return HouseholdsProvider.Entities as IQueryable<Households>;
        }

        public virtual bool ChangePassword(string householdsName, string oldPassword, string newPassword)
        {
            if (!VaildateHouseholds(householdsName, oldPassword))
            {
                return false;
            }
            return ChangePassword(householdsName, newPassword);
        }

        public virtual bool ChangePassword(string householdsName, string newPassword)
        {
            var households = HouseholdsProvider.Get(a => a.UserName == householdsName);

            if (households == null)
            {
                throw new ArgumentException("The member doest not exists.");
            }

            households.Password = PasswordProvider.EncryptPassword(newPassword); ;

            Update(households);

            return true;
        }

        public virtual bool SetIfChangePassword(Households households, string oldPassword, string newPassword)
        {
            if (newPassword.IsNotNullAndNotWhiteSpace())
            {
                if (PasswordProvider.EncryptPassword(oldPassword) != households.Password)
                {
                    return false;
                }
                households.Password = PasswordProvider.EncryptPassword(newPassword);
            }
            return true;
        }

        private void Vaildate(Households households, bool creating = true)
        {
            List<DataViolationItem> violations = new List<DataViolationItem>();
            if (creating && HouseholdsProvider.Get(a => a.UserName == households.UserName) != null)
            {
                violations.Add(new DataViolationItem("UserName", households.UserName, "用户名被占用"));
            }
            if (!creating && HouseholdsProvider.Get(a => a.UserName == households.UserName && a.Id != households.Id) != null)
            {
                violations.Add(new DataViolationItem("UserName", households.UserName, "用户名被占用"));
            }
            if (string.IsNullOrEmpty(households.Password))
            {
                violations.Add(new DataViolationItem("Password", households.Password, "密码格式无效"));
            }

            if (violations.Count > 0)
            {
                throw new DataViolationException(violations);
            }
        }
        public bool IsExistHouseholds(int BuldingNum, int LayersNum, int Numbering)
        {
            if (BuldingNum.IsNull() || LayersNum.IsNull() || Numbering.IsNull()
                || BuldingNum < 0 || LayersNum < 0 || Numbering < 0)
            {
                return false;
            }
            return HouseholdsProvider.IsExist(h => h.BuldiingsNum == BuldingNum && h.LayersNum == LayersNum && h.Numbering == Numbering);
        }
        public bool IsExitHouseHoldsUserName(string HouseHoldsUserName){

            if (HouseHoldsUserName.IsNullOrWhiteSpace())
            {
                return false;
            }
            return HouseholdsProvider.IsExist(h => h.UserName==HouseHoldsUserName);
        }
    }
}
